
package com.joysuch.wwyt.audit.service.impl;

import com.joysuch.wwyt.audit.service.EntityResolver;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.Query;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

@Component
public class EmEntityResolver implements EntityResolver {

    @Autowired
    private EntityManager em;

    @Override
    public <T> T getById(Class<T> clzz, Object value) {
        String ql = "select c from " + clzz.getName() + " as c where c." + extractIdProp(clzz) + " = :value";
        Query query = em.createQuery(ql);
        query.setParameter("value", value);
        return (T) query.getSingleResult();
    }

    private String extractIdProp(Class domainClass) {
        Field[] fields = domainClass.getDeclaredFields();
        for (Field f : fields) {
            if (f.getAnnotation(Id.class) != null) {
                return f.getName();
            }
        }
        PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(domainClass);
        for (PropertyDescriptor pd : pds) {
            if (pd.getReadMethod().getAnnotation(Id.class) != null) {
                return pd.getName();
            }
        }
        Class sc = domainClass.getSuperclass();
        if (domainClass.getSuperclass() != null && sc != Object.class) {
            return extractIdProp(sc);
        }
        throw new IllegalStateException(String.format("类%s没有主键属性", domainClass.getName()));
    }

    @Override
    public <T> List<T> getByProp(Class<T> clzz, String prop, Object value) {
        String ql = "select c from " + clzz.getName() + " as c where c." + prop + " = :value";
        Query query = em.createQuery(ql);
        query.setParameter("value", value);
        List<T> list = query.getResultList();
        return list;
    }

    @Override
    public <T> List<T> getByProp(Class<T> clzz, String prop, Object[] value) {
        String ql = "select c from " + clzz.getName() + " as c where c." + prop + " in (:value)";
        Query query = em.createQuery(ql);
        List<Object> objects = Arrays.asList(value);
        query.setParameter("value", objects);
        List<T> list = query.getResultList();
        return list;
    }

    @Override
    public <T> List<T> getByProp(Class<T> clzz, String prop, List value) {
        String ql = "select c from " + clzz.getName() + " as c where c." + prop + " in (:value)";
        Query query = em.createQuery(ql);
        query.setParameter("value", value);
        List<T> list = query.getResultList();
        return list;
    }

}
